﻿//网络资料
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 200

//整数乘幂运算函数
int Pow(int a, int b)
{
	int i = 0, result = 1;
	for (i = 0; i < b; ++i)
	{
		result *= a;
	}
	return result;
}


//High Precision Of Addition
int myAdd()
{
	char stra[N], strb[N];      //字符串数组，以字符形式储存两个大数；
	int i = 0, step = 4, carry = 0; //step表示块长，carry为进位位；
	int lengtha, lengthb, maxlength, resultsize;    //maxlength表示stra和strb二者长度较大的那个；
	int numa[N], numb[N], numc[N];   //依次储存被加数，加数，和；
	memset(numa, 0, sizeof(numa));
	memset(numb, 0, sizeof(numb));
	memset(numc, 0, sizeof(numc));         //初始化为零；
	scanf("%s%s", stra, strb);
	lengtha = strlen(stra);
	lengthb = strlen(strb);     //计算两个大数的长度
	//字符数字转为四位一块的整数数字
	for (i = lengtha - 1; i >= 0; --i)
	{
		numa[(lengtha - 1 - i) / step] += (stra[i] - '0') * Pow(10, (lengtha - 1 - i) % step);
	}
	for (i = lengthb - 1; i >= 0; --i)
	{
		numb[(lengthb - 1 - i) / step] += (strb[i] - '0') * Pow(10, (lengthb - 1 - i) % step);
	}
	maxlength = lengtha > lengthb ? lengtha : lengthb;

	//逐块相加，并进位
	for (i = 0; i <= maxlength / step; ++i)
	{
		numc[i] = (numa[i] + numb[i]) % Pow(10, step) + carry;    //计算和
		carry = (numa[i] + numb[i]) / Pow(10, step);  //计算进位
	}

	//计算最后和的块的总数
	resultsize = numc[maxlength / step] > 0 ? maxlength / step : maxlength / step - 1;
	printf("%d", numc[resultsize]);
	for (i = resultsize - 1; i >= 0; --i)
	{
		printf("%04d", numc[i]);    //右对齐，补零输出；
	}
	printf("\n");
	return 0;
}

//High Precision Of Subtraction
int mysubtraction()
{
	char stra[N], strb[N];     //字符串数组，以字符形式储存两个大数；
	int i = 0, step = 4, borrow = 0, mark = 0; //step表示块长，borrow为借位位, mark为结果符号位；
	int lengtha, lengthb, maxlength, resultsize;    //maxlength表示stra和strb二者长度较大的那个；
	int numa[N], numb[N], numc[N], * maxnum, * minnum;   //依次储存被减数，减数，和；
	memset(stra, 0, sizeof(stra));
	memset(strb, 0, sizeof(strb));
	memset(numa, 0, sizeof(numa));
	memset(numb, 0, sizeof(numb));
	memset(numc, 0, sizeof(numc));         //初始化为零；
	scanf("%s%s", stra, strb);
	lengtha = strlen(stra);
	lengthb = strlen(strb);     //计算两个大数的长度
	maxlength = lengtha >= lengthb ? lengtha : lengthb;

	//字符数字转为四位一块的整数数字
	for (i = lengtha - 1; i >= 0; --i)
	{
		numa[(lengtha - 1 - i) / step] += (stra[i] - '0') * Pow(10, (lengtha - 1 - i) % step);
	}
	for (i = lengthb - 1; i >= 0; --i)
	{
		numb[(lengthb - 1 - i) / step] += (strb[i] - '0') * Pow(10, (lengthb - 1 - i) % step);
	}

	//找出较大的数
	maxnum = numa;
	minnum = numb;
	mark = 1;
	for (i = (maxlength - 1) / step; i >= 0; --i)
	{
		if (numa[i] > numb[i])
		{
			maxnum = numa;
			minnum = numb;
			mark = 1;
			break;
		}
		else if (numa[i] < numb[i])
		{
			maxnum = numb;
			minnum = numa;
			mark = -1;
			break;
		}
	}

	//逐块相减，并借位
	for (i = 0; i <= maxlength / step; ++i)
	{
		numc[i] = (maxnum[i] - minnum[i] + Pow(10, step) + borrow) % Pow(10, step);    //计算差
		borrow = (maxnum[i] - minnum[i] + Pow(10, step) + borrow) / Pow(10, step) - 1;  //计算借位
	}

	//计算最后和的块的总数
	resultsize = maxlength / step;
	while (!numc[resultsize])    --resultsize;
	printf("%d", mark * numc[resultsize]);
	for (i = resultsize - 1; i >= 0; --i)
	{
		printf("%04d", numc[i]);    //右对齐，补零输出；
	}
	printf("\n");
	return 0;
}

//High Precision Of Multiplication
int mymulti()
{
	char stra[N], strb[N];      //字符串数组，以字符形式储存两个大数；
	int i = 0, j = 0, k = 0, step = 4, carry = 0; //step表示块长，carry为进位位；
	int lengtha, lengthb, resultsize, tmpsize, eachnum;  //resultsize储存块的总数，eachnum用来储存乘数的每一位
	int numa[N], numb[N], numc[N], tmp[N];   //依次储存被乘数数&积，乘数；
	memset(numa, 0, sizeof(numa));
	memset(numb, 0, sizeof(numb));
	memset(numc, 0, sizeof(numc));  //初始化为零；
	scanf("%s%s", stra, strb);
	lengtha = strlen(stra);
	lengthb = strlen(strb);     //计算两个大数的长度
	//将被乘数字符数字转为四位一块的整数数字
	for (i = lengtha - 1; i >= 0; --i)
	{
		numa[(lengtha - 1 - i) / step] += (stra[i] - '0') * Pow(10, (lengtha - 1 - i) % step);
	}
	//将乘数数字字符数字转为一位一块的整数数字
	for (i = lengthb - 1; i >= 0; --i)
	{
		numb[lengthb - 1 - i] = strb[i] - '0';
	}

	resultsize = tmpsize = (lengtha - 1) / step;
	//取乘数的每一位与被乘数的逐块相乘，并进位；
	for (i = 0; i < lengthb; ++i)
	{
		memcpy(tmp, numa, sizeof(numa));    //将numa数组赋值给tmp数组；

		k = i / step;     //k储存每一块需要向高位块移动的次数；
		if (k)
		{
			for (j = tmpsize; j >= 0; --j)
			{
				tmp[j + k] = tmp[j];
				tmp[j] = 0;
			}
			tmpsize += k;
		}

		//乘以乘数每一位扩展成的块；
		eachnum = numb[i] * Pow(10, i % step);
		for (j = 0; j <= tmpsize; ++j)
		{
			tmp[j] *= eachnum;
		}

		//大数相加
		carry = 0;  //进位置零；
		for (j = 0; j <= resultsize; ++j)
		{
			numc[j] += tmp[j] + carry;
			carry = numc[j] / Pow(10, step);
			numc[j] %= Pow(10, step);
		}
		if (carry)
		{
			++resultsize;
			numc[j] += carry;
		}
	}

	//输出
	printf("%d", numc[resultsize]);
	for (i = resultsize - 1; i >= 0; --i)
	{
		printf("%04d", numc[i]);    //右对齐，补零输出；
	}
	printf("\n");
	return 0;
}

//High Precision Of division
//(2)高精度除以高精度
int mydiv()
{
	char stra[N], strb[N];     //字符串数组，以字符形式储存两个大数；
	int i = 0, step = 4, borrow = 0; //step表示块长，borrow为进位位；
	int lengtha, lengthb, tmpnum, numbsize, numcsize, numdsize, maxsize, mark;    //maxlength表示stra和strb二者长度较大的那个；
	int numa[N], numb[N], numc[N], numd[N];   //依次储存被除数数，除数数，商，余数；
	memset(stra, 0, sizeof(stra));
	memset(strb, 0, sizeof(strb));
	memset(numa, 0, sizeof(numa));
	memset(numb, 0, sizeof(numb));
	memset(numc, 0, sizeof(numc));
	memset(numd, 0, sizeof(numd));      //初始化为零；
	scanf("%s%s", stra, strb);
	lengtha = strlen(stra);
	lengthb = strlen(strb);     //计算两个大数的长度

	//字符数字转为四位一块的整数数字
	for (i = lengtha - 1; i >= 0; --i)
	{
		numa[(lengtha - 1 - i) / step] += (stra[i] - '0') * Pow(10, (lengtha - 1 - i) % step);
	}
	for (i = lengthb - 1; i >= 0; --i)
	{
		numb[(lengthb - 1 - i) / step] += (strb[i] - '0') * Pow(10, (lengthb - 1 - i) % step);
	}
	memcpy(numd, numa, sizeof(numa));
	numbsize = (lengthb - 1) / step;
	numcsize = 0;
	numdsize = (lengtha - 1) / step;

	do
	{
		maxsize = numdsize > numbsize ? numdsize : numbsize;
		//计算剩余数是否小于除数
		mark = 1;
		for (i = maxsize; i >= 0; --i)
		{
			if (numd[i] > numb[i])
			{
				mark = 1;
				break;
			}
			else if (numd[i] < numb[i])
			{
				mark = -1;
				break;
			}
		}

		//判断是否余数已经小于除数
		if (!(mark + 1))   break;

		borrow = 0; //借位置零；
		//逐块相减，并借位
		for (i = 0; i <= maxsize; ++i)
		{
			tmpnum = (numd[i] - numb[i] + Pow(10, step) + borrow) % Pow(10, step);    //计算差
			borrow = (numd[i] - numb[i] + Pow(10, step) + borrow) / Pow(10, step) - 1;  //计算借位
			numd[i] = tmpnum;
		}
		while (!numd[numdsize])  --numdsize;

		//每减一个除数，商加一；
		borrow = 1;
		for (i = 0; i <= numcsize; ++i)
		{
			numc[i] += borrow;
			borrow = numc[i] / Pow(10, step);
			numc[i] %= Pow(10, step);
		}
		if (borrow)
		{
			++numcsize;
			numc[i] += borrow;
		}
	} while (1);

	printf("%d", numc[numcsize]);
	for (i = numcsize - 1; i >= 0; --i)
	{
		printf("%04d", numc[i]);    //右对齐，补零输出；
	}
	printf("\n");
	printf("%d", numd[numdsize]);
	for (i = numdsize - 1; i >= 0; --i)
	{
		printf("%04d", numd[i]);    //右对齐，补零输出；
	}
	printf("\n");
	return 0;
}